/*
 * consola.c
 *
 *  Created on: 10/10/2011
 *      Author: MadeYMaga
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <signal.h>
#include "nipc.h"
#include "consola.h"

struct 	sockaddr_un dir;
int 	fd, conectado = 0;


int main(){

	nipcMessage msg = nipc_initmsg;
	int 		retval;
	char 		buffer[80];

	strcpy(dir.sun_path, "/tmp/PPD.temp");
	dir.sun_family = AF_UNIX;

	fd = socket(AF_UNIX, SOCK_STREAM, 0);

	conectar();

	/* Mando info para el Handshake */
	nipc_make(&msg, fd, 0, 0, NULL);

	nipc_send(&msg, fd);

	retval = nipc_recv(&msg, fd);

	if ((retval == NIPC_ERROR) || (msg.type == '-'))
	{
		close(fd);
		printf("> Se cerro la conexion entre consola y PPD.\n");
	}
	else
	{
		printf("\n> Escriba un comando o help para ver los comandos disponibles :)\n");

		do
		{
			memset(buffer, 0, 80);
			printf("> ");
			fgets(buffer, 80, stdin);

			if (NULL != strchr(buffer, '\n'))
				*strchr(buffer, '\n') = '\0';

		}while(buscarComando(buffer));
	}

	if (conectado)
		printf("> Se perdio la conexion con el planificador.\n");

	return 0;
}

int conectar(){

	int con = 0;

	con = connect(fd, (struct sockaddr*) &dir, sizeof(dir));

	if (con != 0)
	{
		printf("> Imposible conectarse con el Planificador. \n");
		close(fd);
		exit(1);
	}

	conectado = 1;

	printf("> La consola se conecto con el planificador.\n");
	return 0;
}

/* Si es quit cierra la conexion sino devuelve 1 */
/* COMANDOS CON PARAMETROS FORMATO: comando(parametro1,parametro2) (sin espacio despues de la coma) */
int buscarComando(char *buffer){

	char *comando = NULL, *parametro = NULL;

	comando = strtok(buffer, "(");

	printf("> Comando: %s\n", comando);

	if(comando == NULL)
	{
		printf("> No se ha ingresado ningun comando...\n");
		return 1;
	}

	parametro = strtok(NULL, ")");

	if(!strcmp("info", comando))
	{
		info();
	}
	else if (!strcmp("clean", comando))
	{
		if (parametro == NULL)
		{
			printf("> Faltan los parametros del clean.\n");
			return 1;
		}
		clean(parametro);
	}
	else if(!strcmp("trace", comando))
	{
		if (parametro == NULL)
		{
			printf("> Faltan los parametros del trace.\n");
			return 1;
		}
		trace(parametro);
	}
	else if(!strcmp("help", comando))
	{
		help();
	}
	else if (!strcmp("quit", comando))
	{
		conectado = 0;
		printf("> Se cerro la conexion con el planificador.\n");
		return 0;
	}
	else {
		printf("> Comando no reconocido. Escriba help para ver los comandos disponibles.\n");
	}

	return 1;
}

int info(){

	nipcMessage msg;
	char buffer[70];

	sprintf(msg.payloadID, "%d", CMD_INFO);
	sprintf(buffer, "info();");
	msg.payloadLength = strlen(buffer)+1;
	msg.payload = buffer;

	if (NIPC_ERROR_NONE != nipc_send(&msg, fd))
		printf("Error al tratar de mandar un mensaje al Planificador. \n");
		conectar();

	nipc_recv(&msg, fd);

	printf("%s \n", msg.payload);

	if (msg.payloadLength)
		free(msg.payload);

	return 1;
}

int help(){

	printf("> Los comandos disponibles son: \n\n");
	printf("> %-15s%s\n", "Comando", "Parametros \n");

	printf("> %-15s%s\n", "info", "sin parametros");
	printf("> Descripcion: Muestra la posicion actual del cabezal.\n\n");
	printf("> %-15s%s\n", "clean", "sectorInicial,sectorFinal");
	printf("> Descripcion: Limpia los sectores de seteando a 0 sus bytes desde el sectorInial hasta el sectorFianl inclusive.\n\n");
	printf("> %-15s%s\n", "trace", "lista de sectores");
	printf("> Descripcion: Muestra el recorrido que realizara el cabezal para atender los pedidos indicados.\n\n");
	printf("> %-15s%s\n", "quit", "sin parametros");
	printf("> Descripcion: Salir del programa. \n\n");

	return 1;
}

int clean(char *sectores){

	nipcMessage msg;
	char buffer[70];

	sprintf(msg.payloadID, "%d", CMD_CLEAN);
	sprintf(buffer, "clean(%s);", sectores);
	msg.payloadLength = strlen(buffer)+1;
	msg.payload = buffer;

	if (NIPC_ERROR_NONE != nipc_send(&msg, fd))
		printf("Error al tratar de mandar un mensaje al Planificador. \n");
		conectar();

	nipc_recv(&msg, fd);

	printf("%s \n", msg.payload);

	if (msg.payloadLength)
		free(msg.payload);

	return 1;
}

int trace(char *sectores){

	nipcMessage msg;
	char 		buffer[70];
	int			i, pistaActual, sectorActual, sector, pista, sectors, tiempoTrans, proxPista, proxSector;

	sprintf(msg.payloadID, "%d", CMD_TRACE);
	sprintf(buffer, "trace(%s);", sectores);
	msg.payloadLength = strlen(buffer)+1;
	msg.payload = buffer;

	if (NIPC_ERROR_NONE != nipc_send(&msg, fd))
		printf("Error al tratar de mandar un mensaje al Planificador. \n");
		conectar();

	nipc_recv(&msg, fd);

	/* llega con pistaActual:sectorActual;
	 * 			 pistaPedida:sectorPedido;
	 * 			 sectoresPorPista;
	 * 			 tiempoTransferencia;
	 * 			 pistaProx:sectorProx
	 */

	pistaActual = atoi(strtok(msg.payload, ":"));
	sectorActual = atoi(strtok(NULL, ";"));
	pista = atoi(strtok(NULL, ":"));
	sector = atoi(strtok(NULL, ";"));
	sectors = atoi(strtok(NULL, ";"));
	tiempoTrans = atoi(strtok(NULL, ";"));
	proxPista = atoi(strtok(NULL, ":"));
	proxSector = atoi(strtok(NULL, ";"));

	printf("> Posicion actual: %d:%d \n", pistaActual, sectorActual);
	printf("> Sector solicitado: %d:%d \n", pista, sector);
	printf("> Sectores recorridos: ");

	if(sectorActual < sector)
	{
		for(i = sectorActual; i < sector; i++)
			printf("%d:%d ", pista, i);
	}
	else
	{
		for(i = sectorActual; i < sectors; i++)
			printf("%d:%d ", pista, i);

		for(i = 0; i < sector; i++)
			printf("%d:%d ", pista, i);
	}
	printf("\n");

	printf("> Tiempo consumido: %d ms.\n", tiempoTrans);

	if(proxPista != -1)
	{
		printf("> Proximo sector: %d:%d \n", proxPista, proxSector);
	}
	else
	{
		printf("> Proximo sector: \n");
	}

	if (msg.payloadLength)
		free(msg.payload);

	return 1;
}
